#include <cstdlib>

#include "LoadShaders.h"

static const GLchar* ReadShader( const char* filename )
{
#ifdef WIN32
    FILE* infile;
    fopen_s( &infile, filename, "rb" );
#else
    FILE* infile = fopen( filename, "rb" );
#endif

    if( !infile ) {
        printf("ReadShader失败\n");
        return NULL;
    }

    fseek( infile, 0, SEEK_END );
    int len = ftell( infile );
    fseek( infile, 0, SEEK_SET );

    GLchar* source = new GLchar[len+1];

    fread( source, 1, len, infile );
    fclose( infile );

    return const_cast<const GLchar*>(source);
}

GLuint LoadShaders( ShaderInfo* shaders )
{
    if( shaders == NULL ) return 0;

    GLuint program = glCreateProgram();

    ShaderInfo* entry = shaders;
    while( entry->type != GL_NONE ) {
        GLuint shader = glCreateShader( entry->type );
        entry->shader = shader;
        const GLchar* source = ReadShader( entry->filename );
        if( source == NULL ) {
            for( entry = shaders; entry->type != GL_NONE; ++entry ) {
                glDeleteShader( entry->shader );
                entry->shader = 0;
            }
            return 0;
        }

        glShaderSource( shader, 1, &source, NULL );
        delete [] source;

        glCompileShader( shader );
        GLint compiled;
        glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
        if( !compiled ) {
            GLsizei len;
            glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &len );

            GLchar* log = new GLchar[len+1];
            glGetShaderInfoLog( shader, len, &len, log );
            std::cerr << "Shader compilation failed: " << log << std::endl;
            delete [] log;
            printf("compiled失败 %s\n", entry->filename);
            return 0;
        }
        glAttachShader( program, shader );
        ++entry;
    }

    glLinkProgram( program );

    GLint success;
    glGetProgramiv( program, GL_LINK_STATUS, &success );

    //对了，在把着色器对象链接到程序对象以后，记得删除着色器对象，我们不再需要它们了
    for( entry = shaders; entry->type != GL_NONE; ++entry ) {
        glDeleteShader( entry->shader );
        entry->shader = 0;
    }

    if ( !success ) {
        return 0;
    }

    return program;

}


